'use client';

import Image from 'next/image';
import React, { useCallback, useState } from 'react';

export interface ImageViewProps {
  ref?: React.Ref<HTMLImageElement>;
  className?: string;
  width: number;
  height: number;
  src: string;
  alt: string;
  draggable?: boolean;
  onClick?: React.MouseEventHandler<HTMLImageElement>;
}

function ImageViewNoMemoized(props: ImageViewProps) {
  const { ref, src, alt, width, height, className, draggable, onClick } = props;
  const [isError, setIsError] = useState(false);

  const shimmer = useCallback(
    (w: number, h: number) => `
<svg width="${w}" height="${h}" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
  <defs>
    <linearGradient id="g">
      <stop stop-color="#333" offset="20%" />
      <stop stop-color="#222" offset="50%" />
      <stop stop-color="#333" offset="70%" />
    </linearGradient>
  </defs>
  <rect width="${w}" height="${h}" fill="#333" />
  <rect id="r" width="${w}" height="${h}" fill="url(#g)" />
  <animate xlink:href="#r" attributeName="x" from="-${w}" to="${w}" dur="1s" repeatCount="indefinite"  />
</svg>`,
    []
  );

  const toBase64 = useCallback(
    (str: string) =>
      typeof window === 'undefined' ? Buffer.from(str).toString('base64') : window.btoa(str),
    []
  );

  const handleLoad = useCallback(() => {
    setIsError(false);
  }, []);

  const handleError = useCallback(() => {
    setIsError(true);
  }, []);

  return (
    <Image
      ref={ref}
      className={className}
      src={src}
      alt={alt}
      width={0}
      height={0}
      sizes="100vw"
      style={{ width, height }}
      placeholder={`data:image/svg+xml;base64,${toBase64(shimmer(width ?? 0, height ?? 0))}`} // loading placeholder
      unoptimized
      priority={false}
      loading="lazy"
      draggable={draggable}
      onError={handleError}
      onLoad={handleLoad}
      overrideSrc={isError ? '/images/image_failed.png' : undefined}
      onClick={onClick}
    />
  );
}

export const ImageView = React.memo(ImageViewNoMemoized);
